package toy.keli.picmap.model;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.ArrayMap;

import com.baidu.mapapi.model.LatLng;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import toy.keli.picmap.tools.Control;
import toy.keli.picmap.tools.Location;
import toy.keli.picmap.util.utilGps;

/**
 * 摘自 https://blog.csdn.net/weixin_39851408/article/details/111803127
 */
public class pic extends  Model{
    public int pid=0;
    public double x=0;
    public double y=0;
    public  String file;
    public String time;
    public String name="";
    public long intime;

    public pic(String name,long time) {
        file=name;
        Map<String,String> exif=getExif(file);
        //Double[] a=getpos();
        //this.setTime(system.file.ctime(name));
        this.x=Double.valueOf(exif.get("lon"));
        this.y=Double.valueOf(exif.get("lat"));
        try {
            String tStr = exif.get("时间");
            long t = new time(tStr, "yyyy:MM:dd HH:mm:ss").getTime() / 1000;
            if (t > 0 && t+300 < time )
                time = t;
        }catch (Exception e){}
        this.setTime(time);
    }

    public pic(String path, long time, float longitude, float latitude) {
        file=path;
        this.setTime(time);
        x=longitude;
        y=latitude;
    }
    public pic(String name) {
        file=name;
        findOne("file='"+file+"'");
    }
    public pic() {

    }

    public pic(int id) {
        findOne("id="+id);
    }

    public static int getCount(String type) {
        long t=Long.valueOf(new pic().find().order("intime asc").where("intime>0").getField("intime"));
        def map=new def.dict("year","yyyy","mount","yyyyMM","day","yyyyMMdd","week","");
        String format=map.get(type).toString();
        time t0=new time(t),tNow=new time();
        int start,end,day=86400*1000;
        switch (type){
            case "mount":
                start=t0.formatInt("yyyy")*12+t0.formatInt("MM");
                end=tNow.formatInt("yyyy")*12+tNow.formatInt("MM");
                return end-start;
            case "day":
                return (int) ((tNow.getTime()-t0.getTime())/day);
            case "week":
                return (int) ((tNow.getTime()-t0.getTime())/(7*day));
            case "year":
            default:
                return Integer.valueOf(new time().format(format))
                        -Integer.valueOf(new time(t).format(format));
        }
    }


    public String getName() {
        if(this.name=="") {
            this.name="";
        }

        return name;
    }

    public void setTime(long time) {
        time*=1000;
        Date Time = new Date();
        Time.setTime(time);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年 MM月 dd日 HH时");
        this.time = formatter.format(Time);
        this.intime=time;
    }

    public Double[] getpos(){
        Map<String,String> exif=getExif(file);
        return new Double[]{Double.valueOf(exif.get("lon")),Double.valueOf(exif.get("lat"))};
    }

    public void wgs2bd(){
        if(x*y>0) {
            double[] a = utilGps.wgs2bd(y, x);
            x = a[1];
            y = a[0];
        }
    }

    @Override
    public boolean save() {
        if(x*y==0) return false;
        boolean rt= super.save();
        if(this.id==0 && file!=null) this.findOne("file='"+file+"'");
        return rt;
    }
    public void copyExifTo(String newFile) {
        Map<String, String> old = pic.getExif(file);
        Map<String, String> info=new ArrayMap<String, String>();
        info.put(ExifInterface.TAG_DATETIME,old.get("时间"));
        info.put(ExifInterface.TAG_MODEL,old.get("型号"));
        info.put(ExifInterface.TAG_MAKE,old.get("制造商"));
        info.put(ExifInterface.TAG_GPS_LATITUDE,old.get("GPS经度"));
        info.put(ExifInterface.TAG_GPS_LONGITUDE,old.get("GPS纬度"));
        info.put(ExifInterface.TAG_GPS_ALTITUDE_REF,old.get("海拔高度"));
        pic.setExif(newFile,info);
    }
    public static Map<String,String> getExif(String path){
            Map<String,String> rt=new LinkedHashMap<String,String>();
            try{
            ExifInterface exifInterface = new ExifInterface(path);
            String guangquan = exifInterface.getAttribute(ExifInterface.TAG_APERTURE);
            String shijain = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
            String baoguangshijian = exifInterface.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
            String jiaoju = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
            String chang = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
            String kuan = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH);
            String moshi = exifInterface.getAttribute(ExifInterface.TAG_MODEL);
            String zhizaoshang = exifInterface.getAttribute(ExifInterface.TAG_MAKE);
            String iso = exifInterface.getAttribute(ExifInterface.TAG_ISO);
            String jiaodu = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);
            String baiph = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
            String altitude_ref = exifInterface.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
            String altitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
            String latitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
            String latitude_ref = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
            String longitude_ref = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
            String longitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
            String timestamp = exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
            String processing_method = exifInterface.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
            //转换经纬度格式
            double lat = score2dimensionality(latitude);
            double lon = score2dimensionality(longitude);
                rt.put("文件名",path.substring(path.lastIndexOf('/')+1));
                rt.put("时间",shijain);
                rt.put("地点","");
                rt.put("长",chang);
                rt.put("宽",kuan);
                rt.put("大小","");
                rt.put("海拔高度",altitude_ref);
                rt.put("光圈",guangquan);
                rt.put("曝光时长",baoguangshijian);
                rt.put("焦距",jiaoju);
                rt.put("型号",moshi);
                rt.put("制造商",zhizaoshang);
                rt.put("ISO",iso);
                rt.put("角度",jiaodu);
                rt.put("白平衡",baiph);
                rt.put("GPS参考高度",altitude);
                rt.put("GPS时间戳",timestamp);
                rt.put("GPS定位类型",processing_method);
                rt.put("GPS参考经度",latitude_ref);
                rt.put("GPS参考纬度",longitude_ref);
                rt.put("GPS经度",latitude);
                rt.put("GPS纬度",longitude);
        /**
         * 将wgs坐标转换成百度坐标
         * 就可以用这个坐标通过百度SDK 去获取该经纬度的地址描述
         */
//            double[] wgs2bd = GpsUtil.wgs2bd(lat, lon);
            rt.put("lon",String.valueOf(lon));
            rt.put("lat",String.valueOf(lat));
        } catch (IOException e) {
            e.printStackTrace();
            rt.put("lon","0");
            rt.put("lat","0");
        }

        return rt;
    }
    public static boolean setExif(String file,Map<String,String> info){
        try {
            ExifInterface exifInterface = new ExifInterface(file);
            for(String key : info.keySet()){
                exifInterface.setAttribute(key,info.get(key));
            }
            exifInterface.saveAttributes();
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public int getRotateDegree() {
        return getRotateDegree(file);
    }
    //Android调用系统相机和相册，解决图片方向问题，压缩图片  https://www.jianshu.com/p/7df654ad02d9
    public static int getRotateDegree(String path) {
        int result = 0;
        try {
            ExifInterface exif = new ExifInterface(path);
            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    result = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    result = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    result = 270;
                    break;
            }
        } catch (IOException ignore) {
            return 0;
        }
        return result;
    }

    private static double score2dimensionality(String string) {
        double dimensionality = 0.0;
        if (null==string){
            return dimensionality;
        }
        //用 ，将数值分成3份
        String[] split = string.split(",");
        for (int i = 0; i < split.length; i++) {
            String[] s = split[i].split("/");
            //用112/1得到度分秒数值
            double v = Double.parseDouble(s[0]) / Double.parseDouble(s[1]);
            //将分秒分别除以60和3600得到度，并将度分秒相加
            dimensionality=dimensionality+v/Math.pow(60,i);
        }
        return dimensionality;
    }

    public void setName(String name) {
        this.name = name;
        this.save();
    }

    public void attrs(callbackDef func) {
        def rt = new def.map(getExif(file));
        rt.set("路径", file);
        rt.set("大小", system.file.sizeFormat(file));
        rt.set("关键字", this.name);
        x = rt.get("lon").toFloat();
        y = rt.get("lat").toFloat();
        this.wgs2bd();
        rt.set("lon",x);
        rt.set("lat",y);
        Location.PointToAddr(new LatLng(y, x), (addr) -> {
//                Pattern p = Pattern.compile("([省市县区])");
//                Matcher m = p.matcher(addr);
//                addr = m.replaceAll("$1 ");
            rt.set("地点", addr);
            if(name.length()==0) setName((String) addr);
            func.call(rt);
        });
    }


    public static void findByPath(String path,callbackName func) {

    }

    public String getStringTime() {
        return new time(this.intime).format("yyyy年MM月dd日 hh:mm");
    }
    public String getStringTime2() {
        return new time(this.intime).format("yyyy年MM月dd日 \nhh:mm");
    }

    public Uri toUrl() {
        return Uri.fromFile(new File(file));
    }

    BitmapFactory.Options bitmapOptions(int ss){
        BitmapFactory.Options opts = new BitmapFactory.Options();
        try {
            FileInputStream fis = new FileInputStream(new File(file));
            opts.inSampleSize = ss;      //只认2的整数倍为有效  赋值为2,那就是每隔2行采1行,每隔2列采一列,那你解析出的图片就是原图大小的1/4
            opts.inJustDecodeBounds = true;        //true to check size
            BitmapFactory.decodeStream(fis, null, opts);
            return opts;
        }catch (Exception e){
            e.printStackTrace();
            return opts;
        }
    }

    public Bitmap thumbnail(int ss) {
        BitmapFactory.Options opts = bitmapOptions(ss);
        return thumbnail(opts.outWidth,opts.outHeight,ss);
    }
    public Bitmap thumbnail(int w,int h) {
        BitmapFactory.Options opts = bitmapOptions(1);
        float w0=opts.outWidth,h0=opts.outHeight;
        if(w*h==0) {
            if (w + h == 0) {
                w = (int)w0;
                h = (int)h0;
            } else if (w == 0) {
                w = (int) (h * (w0/h0));
            } else if (h == 0) {
                h = (int) (w / (w0/h0));
            }
        }

        int ss = (int) Math.min(w0 / w, h0 / h);
        return thumbnail(w, h, ss);
    }
    public Bitmap thumbnail(int w,int h,int ss) {
        try {
            FileInputStream fis = new FileInputStream(new File(file));
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inSampleSize = ss;      //只认2的整数倍为有效  赋值为2,那就是每隔2行采1行,每隔2列采一列,那你解析出的图片就是原图大小的1/4
            opts.inJustDecodeBounds = false;        //true to check size
            Bitmap bitMap= BitmapFactory.decodeStream(fis,null,opts);
            int rd = getRotateDegree();
            Matrix matrix = new Matrix();
            matrix.postRotate(rd);      //旋转
            bitMap = Bitmap.createBitmap(bitMap, 0, 0, Math.min(w,bitMap.getWidth()), Math.min(h,bitMap.getHeight()), matrix, true);
            return bitMap;
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }

    public String getFileName() {
        return file.substring(file.lastIndexOf('/')+1,file.lastIndexOf("."));
    }



    public static interface callbackDef{
        public void call(def v);
    }
    public static interface callbackName{
        public void call(int index,String name,int sum);
    }
    public static interface callback{
        public void call(int index,int sum);
    }

    static Handler myMessageHeader;
    public static  void findByResolver(Activity act,long lastTime,callback func) {
        myMessageHeader=new Handler(){
            public void handleMessage(Message msg){
                int index=msg.getData().getInt("index");
                int sum=msg.getData().getInt("sum");
                func.call(index, sum);
                super.handleMessage(msg);
            }
        };
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    _update(act,lastTime/1000,func);
                }catch (Exception e){}
            }
        }).start();
    }

    private static  void _update(Activity act,long lastTime,callback func) {
        // 获取SD卡的文件，有的比较耗时，一般我们不在Main-Thread线程中去做
        Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        ContentResolver resolver = act.getContentResolver();
        //Android中Cursor的方法 https://blog.csdn.net/ching_zhi/article/details/53835334
        Cursor cursor = resolver.query(uri,new String[]{
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media.DATE_ADDED,
                MediaStore.Images.Media.LATITUDE,
                MediaStore.Images.Media.LONGITUDE,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media._ID
        },"date_added > "+lastTime,null,"date_added desc",null);


        //cursor.moveToFirst();
        int sum=cursor.getCount(),i=0,max= Control.limit;
        def pathAdd=new def();
        sum=Math.min(sum,max);

        while (cursor.moveToNext() && i++ <max) {
            String pathName = cursor.getString(0);
            long time = cursor.getLong(1);
            float latitude = cursor.getFloat(cursor.getColumnIndex(MediaStore.Images.Media.LATITUDE));
            float longitude = cursor.getFloat(cursor.getColumnIndex(MediaStore.Images.Media.LONGITUDE));
            pic p = (latitude == 0 && longitude == 0) ? new pic(pathName,time): new pic(pathName,time,longitude,latitude);
            p.wgs2bd();
            String name=pathName.substring(0,pathName.lastIndexOf("/"));
            path pp=path.get(name);
            p.pid=pp.id;
            boolean b=p.save();
            if(b)  {
                def pathNow=pathAdd.get(name);
                if(pathNow.isEmpyt())  pathAdd.set(name,pathNow=new def());
                pathNow.push(p.id);
                if(pathNow.size()>100) {
                    pp.add(pathNow.size());
                    pathNow.empyt();
                }
                Message m=new Message();
                Bundle d = new Bundle();
                d.putInt("index",i);
                d.putInt("sum",sum);
                m.setData(d);
                myMessageHeader.sendMessage(m);
            }
        }
        cursor.close();
        for(def name : pathAdd)
            path.get(name.toString()).add(pathAdd.get(name).size());

        if(pathAdd.size()>0) func.call(sum,sum);
    }
}
